"""启动恢复器, 根据后台pid恢复启动器"""

import psutil
from typing import List
from src.core import log
from src.core import Enums
from src.db import dbm, dbs
from src.core.variables.exception import *
from .controller import Jar_manager, Static_manager
from src.core.variables.cls import HOSTING_JAVA_RUNNER_DICT, HOSTING_STATIC_RUNNER_DICT


def Java() -> Jar_manager:
    """
    Java runner恢复器
    通过pid对runner进行模拟恢复，由于Unix系统限制，无法完全捕获孤儿进程，因此无法获取其完整的process对象
    """
    from src.db.library.hosting_Java import App
    with dbm.get("hosting_Java") as db_session:
        from sqlalchemy.orm import scoped_session
        db_session: scoped_session
        db_result: List[App] = db_session.query(dbs.hosting_Java.App).all()
        for app in db_result:
            # 如果pid存在
            if app.pid:
                runner = Jar_manager(app.app_id)
                try:
                    orphan = psutil.Process(int(app.pid))
                    if orphan.is_running():
                        runner.pid = app.pid
                        runner.log_path = app.log_path
                        runner.status = Enums.AppStatus.JAVA_STATUS.RUNNING
                        runner.time = int(orphan.create_time() * 1e6)
                        runner.process = orphan
                        match orphan.status():
                            case psutil.STATUS_RUNNING | psutil.STATUS_SLEEPING:
                                runner.status = Enums.AppStatus.JAVA_STATUS.RUNNING
                            # 僵尸进程或其他未知状态
                            case psutil.STATUS_ZOMBIE | _:
                                runner.status = Enums.AppStatus.JAVA_STATUS.ERROR
                    else:
                        runner.status = Enums.AppStatus.JAVA_STATUS.DEAD
                except psutil.NoSuchProcess:
                    ...
            else:
                # pid不存在，app状态为dead，修改数据库
                app.status = Enums.AppStatus.JAVA_STATUS.DEAD.value
                app.pid = ""
                app.log_path = ""
                app.run_path = ""
                runner = Jar_manager(app.app_id)
            if dbm.commit(db_session):
                HOSTING_JAVA_RUNNER_DICT[app.app_id] = runner
                log.INFO(f"Java恢复器：重建 {app.app_id} runner成功！")
            else:
                raise MAIN_EXCEPTION(f"提交数据库更改失败！")
            continue


def Static() -> Static_manager:
    """
    Java runner恢复器
    通过pid对runner进行模拟恢复，由于Unix系统限制，无法完全捕获孤儿进程，因此无法获取其完整的process对象
    """
    from src.db.library.hosting_Static import App
    with dbm.get("hosting_Static") as db_session:
        db_result: List[App] = db_session.query(dbs.hosting_Static.App).all()
        for app in db_result:
            runner = Static_manager(app.app_id)
            # 如果fm_nginx未运行
            if not runner.nginx.status:
                runner.nginx.start()
            HOSTING_STATIC_RUNNER_DICT[app.app_id] = runner
            log.INFO(f"Static恢复器：重建 {app.app_id} runner成功！")